﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;

namespace KeyboardRemapper
{
   public partial class frmEditMacro : Form
   {
      Macro m_macro;
      public static Macro EditMacro(Macro m)
      {
         frmEditMacro editor = new frmEditMacro(m);
         if (editor.ShowDialog() == DialogResult.OK)
            return editor.m_macro;
         else
            return null;
      }

      private frmEditMacro(Macro macro = null)
      {
         InitializeComponent();
         if (macro == null)
            macro = new Macro("1,string ESC");

         m_macro = macro;
         foreach (Keys k in Enum.GetValues(typeof(Keys)))
         {
            if (!cmbKeys.Items.Contains(k.ToString()))
               cmbKeys.Items.Add(k.ToString());
         }
         cmbKeys.Sorted = true;
         txtHotKey.pKeys = new List<int>() { macro.pKey };
         txtHotKey.pDevice = macro.pDevice;
         txtModifiers.pKeys = macro.pModifiers.ToList();
         txtNonModifiers.pKeys = macro.pNotModifiers.ToList();
         if (m_macro.pDevice != -1)
            chkSaveDevice.Checked = true;

         switch (m_macro.pMacroAction)
         {
            case Macro.MacroActionType.Hibernate:
               radHibernate.Checked = true;
               break;
            case Macro.MacroActionType.KeyStroke:
               radKey.Checked = true;
               cmbKeys.SelectedItem = cmbKeys.Items.OfType<string>().Where(name => name == m_macro.pSimulateKey.ToString()).FirstOrDefault();
               break;
            case Macro.MacroActionType.Run:
               radRun.Checked = true;
               txtRunApp.Filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System),
                  m_macro.pRun);
               break;
            case Macro.MacroActionType.Sleep:
               radSleep.Checked = true;
               break;
            case Macro.MacroActionType.WriteString:
               radString.Checked = true;
               txtString.Text = m_macro.pChars;
               break;
            case Macro.MacroActionType.AppMenu:
               radShowMenu.Checked = true;
               lstMenuItems.Items.AddRange(m_macro.pAppList.ToArray());
               break;
            case Macro.MacroActionType.Remember:
               radRemember.Checked = true;
               txtSlot.Value = m_macro.pSlot;
               break;
            case Macro.MacroActionType.GoTo:
               radGoTo.Checked = true;
               txtSlot.Value = m_macro.pSlot;
               break;
            case Macro.MacroActionType.Restart:
               radRestart.Checked = true;
               break;
         }

      }

      private void radAction_CheckedChanged(object sender, EventArgs e)
      {
         cmbKeys.Visible = radKey.Checked;
         txtString.Visible = radString.Checked;
         txtRunApp.Visible = radRun.Checked;
         pnlMenu.Visible = radShowMenu.Checked;
         txtSlot.Visible = radGoTo.Checked || radRemember.Checked;
         if (radGoTo.Checked)
         {
            txtSlot.Top = radGoTo.Top;
            txtSlot.Left = radGoTo.Right;
         }
         else if (radRemember.Checked)
         {
            txtSlot.Top = radRemember.Top;
            txtSlot.Left = radRemember.Right;
         }
      }

      private void btnOk_Click(object sender, EventArgs e)
      {
         string sError = null;
         if (radString.Checked && txtString.Text == "")
         {
            sError = "String field is empty";
         }
         else if (radKey.Checked && cmbKeys.SelectedItem == null)
         {
            sError = "No key selected";
         }
         else if (radShowMenu.Checked && lstMenuItems.Items.Count == 0)
         {
            sError = "Menu is empty";
         }
         else if (radRun.Checked && txtRunApp.Filename == "")
         {
            sError = "No external application selected";
         }
         else if (radRun.Checked && !File.Exists(txtRunApp.Filename))
         {
            sError = "External application does not exist";
         }

         if (sError == null)
         {

            m_macro.pKey = txtHotKey.pKeys[0];
            m_macro.pModifiers = txtModifiers.pKeys;
            m_macro.pNotModifiers = txtNonModifiers.pKeys;
            if (chkSaveDevice.Checked)
               m_macro.pDevice = txtHotKey.pDevice;
            else
               m_macro.pDevice = -1;

            if (radKey.Checked)
            {
               m_macro.pMacroAction = Macro.MacroActionType.KeyStroke;
               foreach (Keys k in Enum.GetValues(typeof(Keys)))
               {
                  if (k.ToString() == (string)cmbKeys.SelectedItem)
                  {
                     m_macro.pSimulateKey = k;
                     break;
                  }
               }
            }
            else if (radString.Checked)
            {
               m_macro.pMacroAction = Macro.MacroActionType.WriteString;
               m_macro.pChars = txtString.Text;
            }
            else if (radSleep.Checked)
               m_macro.pMacroAction = Macro.MacroActionType.Sleep;
            else if (radRun.Checked)
            {
               m_macro.pMacroAction = Macro.MacroActionType.Run;
               m_macro.pRun = txtRunApp.Filename;
            }
            else if (radHibernate.Checked)
               m_macro.pMacroAction = Macro.MacroActionType.Hibernate;
            else if (radShowMenu.Checked)
            {
               m_macro.pMacroAction = Macro.MacroActionType.AppMenu;
               m_macro.pAppList = new frmAppMenu.AppList();
               m_macro.pAppList.AddRange(lstMenuItems.Items.OfType<frmAppMenu.AppInfo>());
            }
            else if (radGoTo.Checked)
            {
               m_macro.pMacroAction = Macro.MacroActionType.GoTo;
               m_macro.pSlot = (int)txtSlot.Value;
            }
            else if (radRemember.Checked)
            {
               m_macro.pMacroAction = Macro.MacroActionType.Remember;
               m_macro.pSlot = (int)txtSlot.Value;
            }
            else if (radRestart.Checked)
            {
               m_macro.pMacroAction = Macro.MacroActionType.Restart;
            }
            DialogResult = System.Windows.Forms.DialogResult.OK;
         }
         else
         {
            MessageBox.Show("Error :" + sError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
         }
      }

      private void btnCancel_Click(object sender, EventArgs e)
      {
         DialogResult = System.Windows.Forms.DialogResult.Cancel;
      }

      private void lstMenuItems_MouseDoubleClick(object sender, MouseEventArgs e)
      {
         if (lstMenuItems.SelectedItem != null)
         {
            frmEditMenuItem.EditMenuItem(lstMenuItems.SelectedItem as frmAppMenu.AppInfo);
         }
      }

      private void btnDelMenuItem_Click(object sender, EventArgs e)
      {
         if (lstMenuItems.SelectedItem != null)
         {
            DialogResult dr = MessageBox.Show("You are about to remove the selected item :\n" +
               lstMenuItems.SelectedItem.ToString() + "\n\nPress Ok to confirm", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (dr == System.Windows.Forms.DialogResult.OK)
               lstMenuItems.Items.Remove(lstMenuItems.SelectedItem);
         }
      }

      private void btnAddMenuItem_Click(object sender, EventArgs e)
      {
         frmAppMenu.AppInfo newItem = new frmAppMenu.AppInfo(@"Notepad,c:\windows\system32\notepad.exe,0,,Notepad");
         if (frmEditMenuItem.EditMenuItem(newItem) == System.Windows.Forms.DialogResult.OK)
            lstMenuItems.Items.Add(newItem);
      }

      private void btnUp_Click(object sender, EventArgs e)
      {
         if (lstMenuItems.SelectedItem != null && lstMenuItems.SelectedIndex > 0)
         {
            int insertAt = lstMenuItems.SelectedIndex - 1;
            InsertSelectedItemAt(insertAt);
         }
      }

      private void InsertSelectedItemAt(int insertAt)
      {
         List<frmAppMenu.AppInfo> selection = new List<frmAppMenu.AppInfo>();
         foreach (frmAppMenu.AppInfo item in lstMenuItems.SelectedItems.OfType<frmAppMenu.AppInfo>().ToList())
         {
            selection.Add(item);
            lstMenuItems.Items.Remove(item);
         }

         selection.Reverse();
         foreach (frmAppMenu.AppInfo item in selection)
         {
            if (insertAt >= lstMenuItems.Items.Count)
               lstMenuItems.Items.Add(item);
            else
               lstMenuItems.Items.Insert(insertAt, item);
         }
      }

      private void btnDown_Click(object sender, EventArgs e)
      {
         if (lstMenuItems.SelectedItem != null)
         {
            int insertAt = lstMenuItems.SelectedIndex + 1;
            InsertSelectedItemAt(insertAt);
         }
      }

   }
}
